package com.hzw.saas.service.product.service;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.hzw.saas.api.product.ILicenseProductService;
import com.hzw.saas.api.product.ILicenseUserService;
import com.hzw.saas.api.product.IProductUpdateService;
import com.hzw.saas.api.product.bo.ProductVersionBO;
import com.hzw.saas.api.product.dto.LicenseUserBO;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.util.enums.AssertEnum;
import com.hzw.saas.service.product.config.ProductConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author EZ09
 * @since 08/03/2021
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ProductUpdateServiceImpl implements IProductUpdateService {

    private final ProductConfig productConfig;
    private final ILicenseProductService licenseProductService;
    private final ILicenseUserService licenseUserService;

    @Override
    public List<ProductVersionBO> listProductVersions(String userId, String productName) {
        String productId = licenseProductService.getIdByName(productName, AssertEnum.FOUND);
        List<LicenseUserBO> licenseUser = licenseUserService.getLicenseUser(userId, productId, AssertEnum.FOUND);
        List<String> licenseVersions = licenseUser.stream().map(LicenseUserBO::getProductVersion).collect(Collectors.toList());
        // 获取产品目录
        File productRoot = this.getProductRoot(productName);
        if (!productRoot.isDirectory()) {
            log.error("产品({})根目录不存在", productName);
            return new ArrayList<>();
        }
        // 版本目录格式 ver.2021A.20210803, 2021A为数据库记录版本号
        File[] versionFolders = productRoot.listFiles(child -> {
            if (!child.isDirectory()) {
                return false;
            }
            String version = this.parseProductVersion(child.getName());
            if (StrUtil.isBlank(version)) {
                return false;
            }
            return this.checkAuth(version, licenseVersions);
        });
        List<ProductVersionBO> result = new ArrayList<>();
        if (Objects.nonNull(versionFolders)) {
            Arrays.stream(versionFolders).forEach(folder -> {
                ProductVersionBO versionBO = new ProductVersionBO();
                versionBO.setProductName(productName);
                versionBO.setProductVersion(this.parseProductVersion(folder.getName()));
                versionBO.setDirectoryName(folder.getName());
                Map<String, String> releaseMap = this.readReleaseFile(folder);
                versionBO.setReleaseVersion(releaseMap.getOrDefault(productConfig.getReleaseVersionKey(), ""));
                versionBO.setReleaseDate(releaseMap.getOrDefault(productConfig.getReleaseDateKey(), ""));
                versionBO.setReleaseNotes(releaseMap.getOrDefault(productConfig.getReleaseNotesKey(), ""));
                result.add(versionBO);
            });
        }
        return result;
    }

    @Override
    public File getProductMetadata(String userId, String productName, String directoryName) {
        String productId = licenseProductService.getIdByName(productName, AssertEnum.FOUND);
        List<LicenseUserBO> licenseUser = licenseUserService.getLicenseUser(userId, productId, AssertEnum.FOUND);
        List<String> licenseVersions = licenseUser.stream().map(LicenseUserBO::getProductVersion).collect(Collectors.toList());
        String version = this.parseProductVersion(directoryName);
        AssertUtil.assertThrow("用户无此版本产品的权限", HttpStatus.FORBIDDEN, !this.checkAuth(version, licenseVersions));
        File file = this.getProductMetadata(productName, directoryName);
        AssertUtil.assertThrow("描述文件未找到", HttpStatus.NOT_FOUND, !file.isFile());
        return file;
    }

    @Override
    public File getProductFile(String userId, String productName, String directoryName, String filePath) {
        String productId = licenseProductService.getIdByName(productName, AssertEnum.FOUND);
        List<LicenseUserBO> licenseUser = licenseUserService.getLicenseUser(userId, productId, AssertEnum.FOUND);
        List<String> licenseVersions = licenseUser.stream().map(LicenseUserBO::getProductVersion).collect(Collectors.toList());
        String version = this.parseProductVersion(directoryName);
        AssertUtil.assertThrow("用户无此版本产品的权限", HttpStatus.FORBIDDEN, !this.checkAuth(version, licenseVersions));
        File file = this.getProductFile(productName, directoryName, filePath);
        AssertUtil.assertThrow("文件未找到: ".concat(filePath), HttpStatus.NOT_FOUND, !file.isFile());
        return file;
    }

    // 版本目录格式 ver.2021A.20210803, 2021A为数据库记录版本号
    private String parseProductVersion(String productVersion) {
        String[] split = productVersion.split("[-]");
        return split.length < 2 ? "" : split[1];
    }

    private File getProductRoot(String productName) {
        return FileUtil.file(productConfig.getReleaseCatalog(), productName);
    }

    private File getProductFolder(String productName, String directoryName) {
        return FileUtil.file(this.getProductRoot(productName), directoryName);
    }

    private Map<String, String> readReleaseFile(File productFolder) {
        File releaseFile = FileUtil.file(productFolder, productConfig.getReleaseFile());
        try (BufferedReader reader = FileUtil.getReader(releaseFile, StandardCharsets.UTF_8)) {
            final String LINE_BREAK = "\r\n";
            final String RELEASE_NOTES_SEPARATOR = "---";
            final String RELEASE_ATTR_SEPARATOR = ":";
            Map<String, String> result = new HashMap<>();
            String lineContent = null;
            StringBuilder releaseNotes = new StringBuilder("");
            boolean isReleaseNotes = false;
            while ((lineContent = reader.readLine()) != null) {
                if (lineContent.startsWith(RELEASE_NOTES_SEPARATOR)) {
                    isReleaseNotes = !isReleaseNotes;
                    continue;
                }
                if (isReleaseNotes) {
                    releaseNotes.append(lineContent).append(LINE_BREAK);
                    continue;
                }
                String[] split = lineContent.split(RELEASE_ATTR_SEPARATOR);
                String key = split[0].trim();
                String value = split.length >= 2 ? split[1].trim() : "";
                result.put(key, value);
            }
            releaseNotes.delete(releaseNotes.lastIndexOf(LINE_BREAK), releaseNotes.length());
            result.put(productConfig.getReleaseNotesKey(), releaseNotes.toString());
            return result;
        } catch (IOException e) {
            log.error("读取release file失败...", e);
            throw new IORuntimeException("读取release file失败...", e);
        }
    }


    private File getProductMetadata(String productName, String directoryName) {
        return FileUtil.file(this.getProductFolder(productName, directoryName), productConfig.getMetadataFile());
    }

    private File getProductFile(String productName, String directoryName, String filePath) {
        return FileUtil.file(this.getProductFolder(productName, directoryName), filePath);
    }

    private boolean checkAuth(String version, List<String> licenseVersions) {
        for (String licenseVersion : licenseVersions) {
            if (ObjectUtil.compare(version, licenseVersion) <= 0) {
                return true;
            }
        }
        return false;
    }

}
